package api

import (
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/gofiber/fiber/v2"
)

type FileHandler struct {
	dataDir string
}

func NewFileHandler(dataDir string) *FileHandler {
	return &FileHandler{
		dataDir: dataDir,
	}
}

// GetFile 提供文件访问 API
func (h *FileHandler) GetFile(c *fiber.Ctx) error {
	// 从 URL 路径中提取文件路径
	// 例如: /api/files/cards/test.txt -> cards/test.txt
	filePath := strings.TrimPrefix(c.Path(), "/api/files/")

	log.Printf("🔍 请求文件: %s", filePath)
	log.Printf("🔍 数据目录: %s", h.dataDir)

	if filePath == "" {
		log.Printf("❌ 文件路径为空")
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code": 400,
			"data": "文件路径不能为空",
		})
	}

	// 构建完整的文件路径
	fullPath := filepath.Join(h.dataDir, filePath)
	log.Printf("🔍 完整文件路径: %s", fullPath)

	// 检查文件是否存在
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		log.Printf("❌ 文件不存在: %s", fullPath)
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
			"code": 404,
			"data": "文件不存在",
		})
	}

	// 检查路径是否在数据目录内（安全措施）
	absDataDir, _ := filepath.Abs(h.dataDir)
	absFilePath, _ := filepath.Abs(fullPath)
	if !strings.HasPrefix(absFilePath, absDataDir) {
		log.Printf("❌ 访问路径超出允许范围")
		return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
			"code": 403,
			"data": "访问被拒绝",
		})
	}

	// 获取文件信息
	fileInfo, err := os.Stat(fullPath)
	if err != nil {
		log.Printf("❌ 获取文件信息失败: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code": 500,
			"data": "获取文件信息失败",
		})
	}

	// 如果是目录，返回目录列表
	if fileInfo.IsDir() {
		return h.listDirectory(c, fullPath, filePath)
	}

	// 返回文件内容
	log.Printf("✅ 返回文件: %s", fullPath)
	return c.SendFile(fullPath)
}

// listDirectory 列出目录内容
func (h *FileHandler) listDirectory(c *fiber.Ctx, fullPath, relativePath string) error {
	entries, err := os.ReadDir(fullPath)
	if err != nil {
		log.Printf("❌ 读取目录失败: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code": 500,
			"data": "读取目录失败",
		})
	}

	var files []fiber.Map
	for _, entry := range entries {
		entryPath := filepath.Join(relativePath, entry.Name())
		info, _ := entry.Info()

		fileInfo := fiber.Map{
			"name":  entry.Name(),
			"path":  entryPath,
			"isDir": entry.IsDir(),
		}

		if info != nil {
			fileInfo["size"] = info.Size()
			fileInfo["modTime"] = info.ModTime()
		}

		files = append(files, fileInfo)
	}

	return c.JSON(fiber.Map{
		"code": 200,
		"data": fiber.Map{
			"path":  relativePath,
			"files": files,
		},
	})
}

// CreateFile 创建文件 API
func (h *FileHandler) CreateFile(c *fiber.Ctx) error {
	var req struct {
		Path    string `json:"path"`
		Content string `json:"content"`
	}

	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code": 400,
			"data": "请求格式错误",
		})
	}

	if req.Path == "" {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code": 400,
			"data": "文件路径不能为空",
		})
	}

	// 构建完整路径
	fullPath := filepath.Join(h.dataDir, req.Path)
	log.Printf("🔍 创建文件: %s", fullPath)

	// 确保目录存在
	dir := filepath.Dir(fullPath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		log.Printf("❌ 创建目录失败: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code": 500,
			"data": "创建目录失败",
		})
	}

	// 写入文件
	if err := os.WriteFile(fullPath, []byte(req.Content), 0644); err != nil {
		log.Printf("❌ 写入文件失败: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code": 500,
			"data": "写入文件失败",
		})
	}

	log.Printf("✅ 文件创建成功: %s", fullPath)
	return c.JSON(fiber.Map{
		"code": 200,
		"data": "文件创建成功",
		"path": req.Path,
	})
}

// RegisterRoutes 注册路由
func (h *FileHandler) RegisterRoutes(app *fiber.App) {
	app.Get("/api/files/*", h.GetFile)
	app.Post("/api/files", h.CreateFile)

	// 调试端点
	app.Get("/debug/data-dir", func(c *fiber.Ctx) error {
		return c.JSON(fiber.Map{
			"data_dir": h.dataDir,
			"exists":   h.dataDirExists(),
		})
	})
}

// dataDirExists 检查数据目录是否存在
func (h *FileHandler) dataDirExists() bool {
	_, err := os.Stat(h.dataDir)
	return err == nil
}
